home *** CD-ROM | disk | FTP | other *** search
/ The Programmer Disk / The Programmer Disk (Microforum).iso / xpro / basic1 / pro10 / macro.doc < prev    next >
Encoding:
Text File  |  1989-04-05  |  50.4 KB  |  1,189 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.                            GLIB Macro-Routines
  7.                       Copyright (C), InfoSoft 1987-1988
  8.  
  9.  
  10.         GLIB contains and premieres several higher-level routines not
  11.     available in ANY other library collection whatever the price.  These
  12.     routines do more, much more, than the average call to simply save the
  13.     screen image or whatever.  These are more like complete programs in
  14.     themselves, yet they remain callable from QB (and in some cases 'C')
  15.     to perform a a function, or set of functions.  For lack of a better
  16.     term, we are calling this type of callable routine a macro-routine
  17.     to differentiate them from simple calls or primitives available from
  18.     most all run-of-the-mill library collections.
  19.  
  20.        The term high-level, as used here, is simply meant to indicate
  21.     that the routine or call is a complete subprogram, not just a sub-
  22.     routine or function.  Many remain in Assembler.
  23.  
  24.  
  25.  
  26.        The macro-routines currently included, and documented here are:
  27.  
  28.       A.  FED    - A complete input handler for editing input.
  29.       B.  Clock  - An installable and accurate time display.
  30.       C.  QCalc  - A complete, full featured calculator.
  31.       D.  FlexMenu - All pupose, flexible menuing routine
  32.       E.  StatLine - A set of status line control routines.
  33.  
  34.  
  35.  
  36.  
  37.  
  38.      A.      Field Editor -  Keyboard Input Handler
  39.              (C) InfoSoft, 1987, 1988
  40.  
  41.  
  42.           I.       Introduction
  43.  
  44.         There are several (indeed many!) text input handlers around.  I
  45.      know, because I have, or have looked at, many of them at one time or
  46.      another.  Many of them require significant editing to work, or they
  47.      are not modular, or they require the event trapping switch, or they
  48.      were inadequate in functionality.  This is not to imply that FED is
  49.      without its own failings, but overall, it is very flexible.
  50.  
  51.           FED, which originally stood for Field EDitor, is modular.  It can
  52.      be called from the main code of another program very easily.
  53.  
  54.           As is, FED is very flexible in most every aspect.  You can change
  55.      most all of the operating parameters with the change of a flag or
  56.      two.
  57.  
  58.           Finally, FED does not require the use of any event trapping
  59.      switch, it identifies extended key codes on its own, like most any
  60.      text input routine should.
  61.  
  62.  
  63.  
  64.           II.          FED Files
  65.  
  66.        The key FED files are:
  67.      FED-DEMO.BAS  - The demo
  68.      EMP.DAT       - A random file of 7 or so records for the demo
  69.  
  70.  
  71.         The demo is a pretty simple random file allowing you to edit the
  72.      various records in the file.  It is especially easy to use after
  73.      reviewing this documentation.  You are encouraged to read this
  74.      first so that as FED-DEMO executes, you can notice some of the key
  75.      features.
  76.  
  77.  
  78.  
  79.  
  80.         III.           FED Parameters, Syntax
  81.  
  82.           FED uses several switches and 3 arguments to control the flow
  83.      and text input.  The formal or direct parameters are:
  84.  
  85.      TEXT$ - The text string to edit.
  86.      FSIZ  - An integer telling FED the maximum length allowed for the
  87.              TEXT$, the current text to be edited.
  88.      FCODE - The exit code returned by FED to tell you HOW they completed
  89.              that field or what key was pressed to exit FED.
  90.  
  91.           You should understand that you can actually use any names that
  92.      suit you in a call to a SUB / END SUB subroutine.  That is, you could
  93.      use ED$ instead of TEXT$, or T$, or whatever you want.  FED will
  94.      operate just as expected, as long as you pass them in the right
  95.      order.  The correct syntax:
  96.  
  97.      CALL fed(text$, fsiz%, fcode%)
  98.  
  99.           The importance of FSIZ is that FED will not allow input after that
  100.      maximum size is reached, and maybe beep (bleep actually).  FED does not
  101.      change FSIZ on the return, so be sure to reset it for each successive
  102.      call.
  103.  
  104.  
  105.  
  106.  
  107.           IV.        Incorporating FED to your code
  108.  
  109.         There are a few simple things to do to get FED running in your
  110.      program:
  111.  
  112.         FED works off of 3 formal arguments (covered above) and several
  113.      COMMON parameters shared with the main, calling program.  This
  114.      allows you to share some parameters with FED very easily such as
  115.      Foreground Color, upper casing etc.
  116.  
  117.         The actual use and meaning of these common parameters are covered
  118.      later, here we are explaining how to set up for FED to work in your
  119.      program.  This is done by simply including the following line in the
  120.      beginning of your main code:
  121.  
  122.    COMMON /fedvars/ fg%, bg%, fgd%, bgd%, alarm%, edited%, nums%, num$,_
  123.           upcase%
  124.  
  125.      It is important that you list them EXACTLY as shown, ie in the order
  126.      shown, WITH the type declarations.  The first four are foreground and
  127.      background colors and the rest are listed alphabetically.
  128.  
  129.  
  130.  
  131.         Note that such COMMON statements must appear in your code BEFORE
  132.      any executable statements.  If you are not familiar with the use of
  133.      COMMON it is suggested that you review this in the QB manual(s).
  134.      Also refer to the FED-DEMO source for proper set up.  In implementing
  135.      the FED variables, we have opted to make several of them COMMON to
  136.      allow FED to read and literally share the value of these variables
  137.      with your main program and at the same time, keeps you from having to
  138.      pass all of them as formal arguments to FED. That is, intead of:
  139.  
  140.      CALL fed(t$, fsiz, fcode, fg, bg, fgd, bgd, alarm, edited, nums,num$,_
  141.               upcase)
  142.      all we do is:
  143.      CALL fed(t$, fsiz, fcode)
  144.  
  145.         Additionally, a benefit of this is that the COMMON switches are
  146.      used or reset MUCH less often in use than say, the text$ would be; for
  147.      example, most likely, you would set the color switches once (fg, fgd,
  148.      bg and bgd), but text$ gets changed at almost every call.
  149.  
  150.         The only restriction in this is that unlike the formal arguments
  151.      passed in the parentheses, the COMMON /fedvars/ variables _MUST_ use
  152.      the variable names shown.  That is, while t$ can be changed to text$
  153.      or fcode can be used as fed.return.code as you please, fg must be
  154.      referenced as fg, fgd as fgd, edited as edited, upcase as upcase etc
  155.      etc.
  156.  
  157.         The use of a blockname (/fedvars/) prevents FED from interfering
  158.      with other COMMON or COMMON SHARED variables, more precisely, it allows
  159.      the USE of additional COMMON or COMMMON SHARED variables.  To name
  160.      additional variables as COMMON declare them like this:
  161.  
  162.      DEFINT a-z
  163.      COMMON /fedvars/ fg%, bg%, fgd%, bgd%, _
  164.              alarm%, editedt%, nums%, num$, upcase%   ' FED block
  165.  
  166.      COMMON SHARED /newblock/ arg1, arg2, arg3        ' different block
  167.  
  168.      COMMON SHARED  a,_                               ' "blank" block of
  169.                     b,_                               '   COMMON variables
  170.                     c,_
  171.                     z
  172.  
  173.         Note that /fedvars/ need not carry the SHARED attribute, but the use
  174.      of a blockname allows FED to share those variables that it needs and
  175.      ONLY those, ie a SIZE error is not encountered if you use other COMMON
  176.      variables.  This allows for maximum flexibility.
  177.  
  178.         Of the /fedvars/ variables, only edt, a more or less auxiliary
  179.      flag is altered by FED.
  180.  
  181.  
  182.  
  183.  
  184.           V.              Internal Editing Keys
  185.  
  186.  
  187.           Internally, FED does several things to provide a professional
  188.      "look" to its operation.  First, lets look at the editing functions
  189.      and keys recognized:
  190.  
  191.      HOME     Places cursor at start of text or field.
  192.      END      Places cursor at first blank at end of the text.
  193.  
  194.  
  195.      Ctrl - End   Clear line from cursor to end of line.
  196.      Ctrl - X     Clear all text from current field.
  197.      Ctrl - U     Undoes current edit.  This does not restore the text to
  198.                   it's form in a disk text file, but restores the text to
  199.                   the form it was UPON ENTRY TO FED.  It cannot know what
  200.                   the text was or what form it was in PRIOR to the CALL.
  201.  
  202.  
  203.      Arrow Keys   Move one character Right or Left.  FED will not allow the
  204.                   user to Cursor right into the hatched area if that
  205.                   means that more than 1 space trails the text.  That is,
  206.                   via the the right arrow, it will not allow more than 2
  207.                   consecutive spaces, as in "J. DOE  " or "J Q  Public".
  208.                   Multiple spaces can be achieved via the insert key
  209.                   or space however.
  210.  
  211.  
  212.      Ctrl-Arrow   Moves one word right or left
  213.      Keys
  214.  
  215.  
  216.      Tab         Moves over 5 spaces without disturbing text.
  217.  
  218.  
  219.      Ins         Insert works as expected, allowing text to be inserted at
  220.                  the cursor, and changes the cursor to a block.  The Insert
  221.                  state is toggled off upon exiting FED or "finishing" the
  222.                  field or text.
  223.  
  224.  
  225.      Del         As expected, deletes characters right of the cursor.
  226.  
  227.  
  228.        No key state flags (such as a [ INS ] or [ Caps ] indicator) are
  229.      put to the screen.  This was viewed as intrusive in that where FED
  230.      places the flag could be an unacceptable location in some applications,
  231.      and it seemed to not be in the interest of speed, to be painting and
  232.      repainting such indicators.
  233.  
  234.  
  235.  
  236.  
  237.  
  238.           VI.              FED Return Codes - FCODE
  239.  
  240.           This is the half of the meat of the program (The other half is
  241.      internal).  FCODE returns to you a value dependent on what key is
  242.      pressed to complete the editing of the text.
  243.  
  244.           Needless to say, FED has undergone several forms and formats since
  245.      I first started work on it.  The object of most changes has been to
  246.      make the FCODEs more intuitive.  The current state may not seem to be
  247.      as intuitive as they could be at first glance, but in keeping the dual
  248.      goals of ease of use AND flexibility, but the actual FCODE handler
  249.      (the routine called CHGFLD in FED-DEMO) can be "canned", or predone to
  250.      be incorporated into your program.
  251.  
  252.  
  253.                               FCODE Returns:
  254.  
  255.                              Enter   -    0
  256.               F1      -    1                 F8      -    8
  257.               F2      -    2                 F9      -    9
  258.               F3      -    3                F10      -   10
  259.               F4      -    4                PgUp     -   11
  260.            Up Arrow   -    5                PgDn     -   12
  261.            Dn Arrow   -    6              Ctrl-PgUp  -   13
  262.               F7      -    7              Ctrl-PgDn  -   14
  263.                              Escape  -    15
  264.  
  265.  
  266.           Note that not EVERY possible key is trapped or returned.  Most
  267.      notably, F5 and F6 are not trapped.   This is not because FED is lazy
  268.      or dumb, but simply to cut down on the number of FCODES you need to
  269.      handle (and handle whether your program uses or needs those codes or
  270.      not) and to leave 2 keys open for response to any standing ON KEY() key
  271.      traps your main program may need to have active at all times.
  272.  
  273.         I have used FED in hundreds of applications and more often than
  274.      not, the keys trapped as is, are MORE than enough to do the job.  If
  275.      you look at FED-DEMO you will see that it does quite a bit, in record
  276.      paging, abort and save keys, and still has 3 or 4 FCODEs unused. In
  277.      the long run, you should find that FED offers a sufficient number of
  278.      editing keys and with the use of a pre-done ChangeField routine, it
  279.      should be easy to handle the number of FCODES that it can return.
  280.  
  281.  
  282.  
  283.  
  284.         VII.         Internal Handling, COMMON Parameters
  285.  
  286.          FED does a few things internally on its own and a few others you
  287.      control and change throughout the course of your program by resetting
  288.      the COMMON parameters.  If you are not familiar with SHARED parameters
  289.      you should refer to your QB manual.  These are not passed as formal
  290.      arguments inside the parentheses when the program is CALLed but are set
  291.      in your main program.
  292.  
  293.  
  294.        Using the value of FSIZ as the maximum length allowed, FED provides
  295.      hatching from the end of the actual text to that maximum length.
  296.      If a string is longer than FSIZ upon entry to FED, it is truncated to
  297.      the maximum length.
  298.      ( It is important to note that upon GETting a string from a random
  299.      file, QB pads the string with spaces from the end of the text for the
  300.      length of the FIELD.  That is, if you LSET "JOHN DOE" in a FIELD 15
  301.      characters long, after a GET, the name becomes "JOHN DOE       ".  If
  302.      you pass this as is to FED with a FSIZ of 15, no hatching will appear
  303.      because FED does not distinguish the spaces as blank text or
  304.      attempt to modify the string.)
  305.  
  306.      - FED also highlights the current text or data as well as providing
  307.      the hatching.  When the editing is completed, and one of the 15 FCODE
  308.      keys are hit to exit the field (actually FED is exited, and control is
  309.      returned to you), the highlighting is turned off.  This color control
  310.      is handled thru the use of 2 sets of color codes: FG, BG and FGD and
  311.      BGD.  These must be assigned valid BASIC color codes in the course of
  312.      your main code.  At the start, FED uses the FGD, BGD (as in
  313.      ForeGround_Data, BackGround_Data) colors and upon exiting, redisplays
  314.      it in the FG, BG colors.  These only need to be set once.
  315.  
  316.      - Caps or uppercase input from the keyboard can be forced on the fly
  317.      (ie without a separate call) via the UCASE switch.  Set UPCASE to 1
  318.      or non zero for caps, 0 for to allow either lower or upper case.
  319.      Note: Previous to GLIB 1.3, this parameter was named 'ucase', starting
  320.      with GLIB 1.3, this is renamed 'upcase' to avoid conflicting with
  321.      QB4's statement UCASE$.
  322.  
  323.  
  324.      - Numbers ONLY can be selected in the same manner with the switch
  325.      NUMS.  When this is set, only numeric input is allowed, so to allow
  326.      for a mixed string such as an address, NUMS should be OFF (nums=0).
  327.      Additionally, you can redefine allowable characters for different
  328.      entries via NUM$.  For example, in a phone number entry the characters
  329.      "()-" may be allowable beyond 0-9, but in a dollar based entry $ and
  330.      "." may be allowable.  So prior to the CALL for a phone entry NUM$
  331.      would be set to "1234567890()-", or ".1234567890$" for the dollar
  332.      based entry.  This method of defining the entire string rather than
  333.      just the extra ()-$ or . characters was chosen to allow category type
  334.      entries also.  That is, to force, say a gender selection of M or F,
  335.      set UPCASE to 1, NUMS to 1 and NUM$ to "MF".  If NUM$ is set to null,
  336.      (num$=""), it defaults to "1234567890".
  337.  
  338.  
  339.  
  340.      - If the text string upon exiting FED is different than it was at the
  341.      start of the CALL to fed, then EDITED is set to non-zero.  This
  342.      allows you to test to see if field in a record has been altered.  FED
  343.      only sets it to 1 never to 0.  Since FED is just handling the input
  344.      for different strings, it never knows when a set of fields equalling a
  345.      full record is completed.  EDITED is how FED tells you that something
  346.      has indeed been edited.
  347.      ( Using this flag, you can include code in your ChangeField routine
  348.      to flash a message that an EDIT is in process, as is done in FED-DEMO.
  349.      It is also useful in precluding certain functions if an edited record
  350.      is not  saved.  An example of this is shown in FED-DEMO where paging
  351.      is disallowed if a record is edited and unsaved.
  352.  
  353.      -  The final COMMON parameter to cover is ALARM, this is a switch to
  354.      indicate whether sound is to be on or off.  The sound is more of a
  355.      bleep than a beep.  If this switch is set (non zero) it allows the
  356.      bleep sound effect to sound at various times:
  357.      - An attempt to cursor right when the string has reached FSIZ (maximum
  358.        length).
  359.      - An attempt to enter an invalid character (an alpha character when
  360.        nums is ON).
  361.      - When an inserted character will cause the text to exceed the maximum
  362.        length.
  363.      - Cursor left attempted left of first character position.
  364.      - If cursor right appends more than 1 successive blanks to the text.
  365.  
  366.        Regardless of the state of bleep, FED disregards any such illegal
  367.      activities.  Alarm just adds an error sound to the process.  While the
  368.      error sound has it's uses, it is not recommended that it be on all the
  369.      time - there are time when it is inappropriate.  In such cases, (such
  370.      as in an office bullpen setting where such BLEEPING would be
  371.      annoying), clear the Alram flag (Alarm = 0).
  372.  
  373.         In summary, the COMMON switch (0 or 1) parameters are:
  374.      UPCASE    -   Convert alpha input to Uppercase
  375.      NUMS      -   Allow (numeric) input only from NUM$
  376.      NUM$      -   Character string filter of allowable input to be used
  377.                    if NUMS is not 0.
  378.      FGD, BGD  -   Foreground and Background colors to display the string in
  379.                    while that string is undergoing editing via FED.
  380.      FG, BG    -   Colors FED restores the string to upon exiting FED.
  381.      EDITED    -   Flag set by FED to show if text is changed.
  382.      ALARM     -   Switch to turn on or off BLEEPER error signal.
  383.  
  384.  
  385.  
  386.  
  387.                                 B.  CLOCK
  388.  
  389.  
  390.     I.    Introduction
  391.  
  392.     CLOCK allows your program to provide an ongoing display of the time
  393.     time WITHOUT the hassle, heartache or overhead of executing GOSUB
  394.     statements to print TIME$.
  395.  
  396.     CLOCK works much the same as a DOS level TSR, that is, it installs
  397.     itself in memory, latching onto to certain system functions or
  398.     interrupts to update a display of the current time as needed.  The
  399.     format of the time display is " hh:mm:ss ?m ".  The hour display is
  400.     in 12 hour format, with a trailing am or pm label.
  401.  
  402.     The problem with most similar time display programs is that they are
  403.     not accurate!  Over the long haul, a simple time keeping process is
  404.     most likely to lose about .2 seconds each second.  This may sound
  405.     trivial or insignificant, but in a mere 5 minutes, the time display
  406.     can be off as much as 2 or 3 seconds!!  If your program is to run for
  407.     hours on end, after a few hours, the time display will simply be
  408.     inaccurate to a wholly unacceptable degree.
  409.  
  410.     To rectify this, CLOCK uses a secondary internal clock to estimate
  411.     the amount of time lost from 'True' system time and periodically
  412.     jumps ahead a second to adjust.  The CLOCK in GLIB does not loose
  413.     an entire second until over 8 hours have passed!  During that time,
  414.     CLOCK's time display consistently remained within a constant .5 to
  415.     1 second of the actual system time returned by TIME$.  In fact, after
  416.     12 hours, CLOCK is incredibly still within 1 second!  Over extremely
  417.     long periods, even CLOCK will eventually vary from true time, so for
  418.     applications that run continually, to adjust the time simply uninstall
  419.     and immediately re install CLOCK.  This will allow it to re-synch with
  420.     the system time for another 8 to 10 hours.
  421.  
  422.     Accuracy is only part of the superiority of CLOCK.  The friendly 12
  423.     hour-based display with the am/pm label provides a positive, easy to
  424.     read display and the time display is fully configurable: it can be
  425.     located or 'popped up' any where on the screen and in any color
  426.     attribute.  CLOCK will also emit a small, pleasant audible tone on
  427.     the hour and on the half hour even this is configurable.
  428.  
  429.     Since CLOCK does take of advantage of TSR-like programming techniques,
  430.     it is installed rather than simply called, to invoke it.  Likewise it
  431.     must be uninstalled prior to your program termination.  It is advised
  432.     that you fully develop and write your program without CLOCK installed
  433.     and only when it is fully debugged should you add CLOCK to your code.
  434.  
  435.     There is no stand alone time display nearly as accurate as CLOCK.
  436.  
  437.  
  438.  
  439.     II.    Syntax
  440.  
  441.     The syntax to implementing CLOCK is very simple:
  442.  
  443.     CALL CLOCK(row, col, attr, FUNC)
  444.     row  - The CRT line to display the time display at.
  445.     col  - The CRT column to display it at.
  446.     attr - The color in attribute form to use in the display.
  447.     FUNC - CLOCK function to perform:
  448.            0 = uninstall clock
  449.            1 = normal installation
  450.            2 = quiet installation (do not beep at half hour intervals.)
  451.  
  452.  
  453.  
  454.     Since CLOCK uses TSR type programming techniques, it must be
  455.     uninstalled when you are done with it.  This cannot be understated:
  456.     CLOCK MUST BE UNINSTALLED BEFORE PROGRAM TERMINATION.
  457.  
  458.     This includes program crashes!  In the event of a runtime error or
  459.     crash, CLOCK must be uninstalled before your application exits to DOS.
  460.     This means if you use ON ERROR type error traps, a call to uninstall
  461.     CLOCK should be performed.  Since CLOCK takes over some very key
  462.     system interrupts, it is not advised that you use it with other TSR
  463.     type programs or routines without a THOROUGH checking out of their
  464.     compatibility.
  465.  
  466.  
  467.  
  468.     III.   Programming Considerations
  469.  
  470.     CLOCK cannot be accidentally twice, CLOCK checks for such an attempt
  471.     and precludes it.  Should you wish to change the attributes or
  472.     location of the display, perform two calls: the first to uninstall
  473.     CLOCK then another to reinstall it with the new color or location (or
  474.     both).  CLOCK does no internal display preservation, so should you do
  475.     an uninstall-install routine to change color or location, the last
  476.     image of the first clock installation will remain unless you restore
  477.     that portion of the screen or CLS or whatever.
  478.  
  479.  
  480.  
  481.                            C.  QCalc
  482.  
  483.  
  484.  
  485.        I.      Introduction
  486.  
  487.  
  488.        QCalc is one of the most powerful and useful callable subroutine in
  489.        _any_ QB/BASCOM add on package.  QCALC has every feature found in a
  490.        cheap calculator, plus some.  QCalc handles values ranging from
  491.        -2.147 to +2.147 BILLION in either decimal or fixed point (as in
  492.        dollar values).
  493.  
  494.        Such a full featured routine is great in and of itself, but being
  495.        written entirely in assembler, QCalc takes _under_ 6k in your
  496.        program and includes an internal screen-save/restore function!
  497.        QCalc is completely self sufficient: all keyboard, video,
  498.        bios and math calculations are _internal_ to it.  There are
  499.        no dependencies on other library routines you may or maynot
  500.        have available to you!
  501.  
  502.  
  503.        Any sort of bookkeeping or number based QB/BASCOM application
  504.        can benefit greatly from QCalc.  QCalc is _not_ a TSR but
  505.        it does remember the result from the last invocation within
  506.        the same application!
  507.  
  508.  
  509.  
  510.        II.  Calculator Operation
  511.  
  512.        When first invoked, QCalc will draw a representation of a
  513.        small hand held calculator on the screen, complete with
  514.        number keys and math operators.  This true to life representation
  515.        makes it ideal for accounting type systems where the user
  516.        or operator is not necessarily a computer aficionado.
  517.  
  518.        QCalc invokes the Num-Lock key for even more convenience, and
  519.        as numbers are pressed, the presses are replicated on the
  520.        calculator display.  Remember, all this power is available to
  521.        you and your program with a simple CALL invocation.
  522.  
  523.        The default mode is Decimal Fixed Point entry since that is
  524.        the most likely method for adding sales, calculating tax etc.
  525.  
  526.  
  527.        Math Functions supported:
  528.  
  529.        + ... Addition
  530.        - ... Subtraction
  531.        * ... Multiplication
  532.        / ... Division
  533.        = ... Equals (the Enter key also acts as an implicit equal sign).
  534.  
  535.  
  536.  
  537.  
  538.        Numeric Entry:
  539.  
  540.        In Fixed Point mode, the decimal can be used to fix the point.
  541.        That is, entering 1 - 2 - 3 - 4 would result in a display of
  542.        1234.00, however, 1 - 2 - . - 3 - 4 would result in 12.34.
  543.  
  544.        Commas are not supported as entry characters in decimal mode,
  545.        however they are displayed as needed.
  546.  
  547.  
  548.        Other Calculator Operations:
  549.  
  550.        [Alt -] \  Changes the sign of the entry (like the '+/-'
  551.        [Alt +] /  key on a calculator).  Note that these are
  552.                   the _top row_ plus and minus keys, not the
  553.                   grey ones.  We would gladly use the grey one
  554.                   also or instead, but the BIOS does not read
  555.                   them when used in combination with the Alt key.
  556.  
  557.  
  558.        As operations are performed, and results displayed, QCalc
  559.        simulates a physical calculator by retaining a display of the
  560.        last 5 entries or results, ie a tape.
  561.  
  562.        [Esc], [Alt-Q]  Abortive type exit - nothing returned
  563.        [Alt-R]         Alt-R, for RETURN, closes the calculator window
  564.                        and returns to your application, returning
  565.                        the last result shown on the calculator.
  566.        [Alt-E], <E>    E or Alt-E is for Clear Entry
  567.                        Clears the number being entered or already entered.
  568.        [Alt-C], <C>    C or Alt-C is Clear All
  569.                        Clears the entry and history by scrolling
  570.                        the tape to clear.
  571.  
  572.        [Alt-D]         Selects Decimal as the operating base.  This
  573.                        is the default when first called.  Should you
  574.                        switch to Fixed Point, QCALC will remember and
  575.                        come up in that mode.
  576.        [Alt-F]         Selects Fixed Point as the operating mode.
  577.  
  578.  
  579.        BackSpace       The backspace key is fully supported while entering
  580.                        digits.  When used on a result, the backspace key
  581.                        acts as the Clear Entry key.
  582.  
  583.  
  584.  
  585.  
  586.        Just as in a physical calculator, a result can be rolled over into
  587.        an entry.  Example:
  588.  
  589.        4 *     ; an entry
  590.        4 =     ; 4*4 = ??
  591.        16=     ; 16 is a _result_
  592.          +     ; tapping plus turns 16 into an _entry_ !
  593.        16+
  594.  
  595.  
  596.  
  597.        III       Operation Tips
  598.  
  599.        QCalc can do any addition, multiplication, division or
  600.        subtraction as long as the result and both operands are within
  601.        the +/- 2.147 BILLION range.  Overflowing or underflowing this
  602.        range will cause numbers to wrap: ie 2.147 BILLION plus 1 =
  603.        - 2.147 BILLION and vice-versa.
  604.  
  605.        Percentages, as in a tax calculation, are easily handled with
  606.        multiplication or division:
  607.  
  608.        Method 1 ( 2 step process):
  609.        Tax rate of 5% on 34.65
  610.  
  611.        34.65 *          ; result of addition etc turned into entry
  612.          .05            ; enter as "." - "0" - "5"
  613.            =            ; hit enter or equal
  614.         1.72            ; this is the 5% tax amount (a _result_ !)
  615.              +          ; turn result into entry
  616.        34.65 =          ; add back in the taxable amount
  617.        36.37            ; Total amount due
  618.  
  619.             Note:  For various reasons, the 5% amount, which is actually
  620.                    1.728 is returned as 1.72 not rounded to 1.73.
  621.  
  622.  
  623.        Method 2 (1 step process):
  624.  
  625.        34.65 *          ; result of addition etc turned into entry
  626.         1.05            ; enter as "1" - "." - "0" - "5"
  627.            =            ; hit enter or equal
  628.        36.38            ; this is the 5% tax amount (a _result_ !)
  629.  
  630.              Note:  This is not only simpler and faster, it is more
  631.                     accurate!  However many people do not understand
  632.                     that the total amount is going to be 100% of the
  633.                     taxable amount _plus_ 5%, ie 105% or (n * 1.05).
  634.  
  635.                     To be able to isolate the tax amount, as might be
  636.                     needed on an itemized bill, just roll over the result
  637.                     into an entry and subtract the subtotal.  Continuing
  638.                     from above, this is done like this:
  639.  
  640.            -            ; roll result into a entry
  641.        34.64            ; deduct the subtotal
  642.         1.73 =          ; the amount added to subtotal ie the tax.
  643.  
  644.  
  645.  
  646.  
  647.        IV        Syntax and Programming Considerations
  648.  
  649.        A. QuickBASIC Syntax
  650.  
  651.        The immense power and functionality of QCalc is invoked with
  652.        a mere 5 parameters that control virtually everything:
  653.  
  654.        Syntax:
  655.  
  656.        DECALRE FUNCTION QCalc&(Row%, Col%, Body%, Scrn%, Button%, SpeedMode%)
  657.        ..
  658.        ..
  659.        ..
  660.        RetVal& = Calc(Row, Col, Body, Scrn, Button, SpeedMode)
  661.  
  662.  
  663.  
  664.        B. Turbo-C Version
  665.  
  666.       extern long near qcalc(int row, int col, int body, int scrn, int msg);
  667.        ..
  668.        ..
  669.        ..
  670.       long retval = 0;
  671.       retval = qcalc(row, col, a, b, c);
  672.       printf("%ld",retval);
  673.  
  674.  
  675.       For the large memory model, simply substitute 'far' for 'near' in
  676.       the declaration.
  677.  
  678.  
  679.  
  680.        C. Parameters:
  681.  
  682.        RetVal&  -  QCalc will return to you the last _result_ value
  683.                    on the QCalc display.  An entry value will not
  684.                    be returned.  That is, entering '1+1=' will return
  685.                    2.  Simply entering 1 only, with no operation, will
  686.                    return the result of the last operation.
  687.  
  688.                    This _must_ be a long integer.  See the warning below.
  689.  
  690.        Row, Col -  Denotes the upper left row, col coordinates for
  691.                    the calculator display.  The size of the calculator
  692.                    display is 31 characters wide, 20 columns tall - roughly
  693.                    1/3rd of the screen.  QCalc is not only functional
  694.                    but it is very smart too: should you pass invalid
  695.                    coordinates for the row/col, it will adjust them so
  696.                    that the calculator display does not wrap.
  697.  
  698.  
  699.  
  700.        Three attribute values are passed to customize the calculator
  701.        display to specifically your needs.  QCalc will use the correct
  702.        display mode for mono vs color/ega/vga displays, but does no
  703.        second guessing on the attributes you pass.  Be sure that the
  704.        attributes you choose are appropriate for the display present.
  705.        EGA's must be in 25 row mode or QCalc simply exits gracefully.
  706.  
  707.        Body     -  The color to use in the calculator body.  This
  708.                    is the predominant color used.
  709.  
  710.        Screen   -  The color to use on the 5 line calculator display.
  711.                    Since the end user will be focusing on this, it
  712.                    should be an easy to read color, however certain
  713.                    attributes can replicate a LCD appearance to
  714.                    make the display even more realistic.
  715.  
  716.        Button   -  This color is used a very little, only to simulate
  717.                    button presses and the like.  Since it is used on
  718.                    the calculator body, some very interesting effects
  719.                    can be created using totally different background
  720.                    colors or the same so that just the key text changes.
  721.  
  722.     SpeedMode   -  This allows the programmer or end user to tailor
  723.                    a portion of the operation characteristics.  When
  724.                    a numeric key (0-9), E or C is pressed, the appropriate
  725.                    display is briefly recolored with the Button Color and
  726.                    a tone sounds.  The SpeedMode parameter allows you to
  727.                    set the duration for the tone in clock ticks (1 / 18.2
  728.                    seconds (we suggest 2).  This time is not system
  729.                    dependant so it makes no difference is QCALC is called
  730.                    on a 386 or a 8088 machine.  However, you may want
  731.                    to turn off the beep tone or speed it up or slow it
  732.                    down the SpeedMode parameter affords you this option.
  733.  
  734.                    Additionally, after the beep, QCALC purges the keyboard
  735.                    buffer of type ahead characters, which is also disabled
  736.                    with the SpeedMode parameter.
  737.  
  738.                    SpeedModes 0 to 4 do not purge the type ahead buffer
  739.                    and represent in clock ticks, how long the tone should
  740.                    sound in the beep/button recolor operation.  Zero is
  741.                    the shortest, with the beep/recolor disabled, four
  742.                    is the longest with it taking about 1/2 second (twice
  743.                    as long as a BASIC or DOS Error BEEP !).  For reference,
  744.                    we recommend 2.
  745.  
  746.  
  747.                    SpeedModes 5 to 9 represent the same clock tick count
  748.                    as 0 to 4, that is, SpeedMode 5 disables the beep with
  749.                    the difference being that SpeedMode 5 to 9 DO purge the
  750.                    type ahead buffer.  So SpeedMode 7 provides the same
  751.                    display effect as 2 with the difference being that 7
  752.                    will eat up any keys waiting in the keyboard buffer.
  753.  
  754.  
  755.  
  756.        V.     Programming Considerations
  757.  
  758.        QCalc returns the last _result_ on the display to your program.
  759.        This means that in a book work type program, you could pop up
  760.        QCalc to allow the user to add up sales or paid outs, and when they
  761.        leave QCalc via [Alt-R], QCalc will return the last result shown
  762.        on the calculator display!  Your program could then automagically
  763.        insert that value on the screen and the proper variable!
  764.  
  765.        If the user leaves QCalc via [Esc] or [Alt-Q], QCalc simply 'pops
  766.        down' and does not attempt to return anything.  You can force a
  767.        return to your program by simply setting up a loop until QCalc DOES
  768.        return a value.  This maybe helpful in cases where the calculator
  769.        covers up some of the entry items on the screen forcing the user to
  770.        occasionally 'pop down' to read more info.  Ex:
  771.  
  772.  
  773.        DO UNTIL RetVal& <> 0
  774.            RetVal& = QCalc(row, col, attrs, attrb, attrf, speed)
  775.  
  776.            IF RetVal& = 0             ' no return
  777.                LOCATE 23, 10
  778.                PRINT "Return Required - Press any key for calculator."
  779.            ELSE
  780.                EXIT DO                ' return was okay get outta LOOP
  781.            END IF
  782.  
  783.            x$=INPUT$(1)               ' get a key, any key
  784.            LOCATE 23,10               ' cover over msg
  785.            PRINT SPACE$(46)
  786.        LOOP
  787.  
  788.  
  789.  
  790.        NOTE!  NOTE!  NOTE!
  791.  
  792.        QCalc returns a _LONG_ integer.  These are 32 bits and requires
  793.        that your receiving variable must be an _LONG_integer.  Attempting
  794.        to assign the result to an integer _will_ result in OVERFLOW.
  795.  
  796.        The return is in decimal mode.  If your application is using
  797.        fixed point numerics, simply divide the return by 100.
  798.  
  799.        This means for 'C' you must use the size identifer 'l' in the
  800.        printf statement of garbage will result of the result returned
  801.        is larger than 32k.  Example:
  802.  
  803.        printf("%ld",retval);
  804.  
  805.  
  806.  
  807.  
  808.        Notes
  809.  
  810.        Within the same program (ie without CHAINing, RUNning or spawning a
  811.        new module), QCalc retains the display of the last entry or result.
  812.        Theoretically, this allows the user to pop up QCalc, add up some
  813.        numbers, pop down to get more info from the screen and return to
  814.        right where they were - previously entered data is _not_ lost!
  815.  
  816.        It is also important to note that second and third and fourth
  817.        calls to QCalc do _not_ have to be at the same location for
  818.        QCalc to pop up the same display!
  819.  
  820.        QCalc is so incredibly intuitive that if on a second call, it
  821.        sees that you have altered the screen color it will not restore
  822.        the screen image, but will redraw the screen with the new colors.
  823.        This prevents the calculator screen from changing colors as it
  824.        scrolls, the tape display is lost, but the last result is _still_
  825.        preserved!
  826.  
  827.        So, while subsequent calls need not be to the same screen
  828.        location, they should be with the same screen colours.
  829.  
  830.  
  831.        QCalc automagically engages the Num Lock key when invoked and
  832.        retores it when exiting.  Since we are not afflicted with one of
  833.        the 'enhanced' 10x key keyboards, we are not yet sure what this
  834.        does with them.  However it is in deference to them and their
  835.        nonspatial-kinesthetic layout that no function keys are used.
  836.  
  837.  
  838.  
  839.        We hope you enjoy QCalc and find it's vast power and incredible
  840.        ease of use to be of benefit in your program.  We are currently
  841.        attempting to port it to 'C' language so that should you learn
  842.        'C' or are already somewhat multi lingual, this invaluable tool
  843.        can 'go with you' and your programming endeavors.
  844.  
  845.  
  846.        QuickBASIC 3.0 users note:
  847.  
  848.        1) Get on the ball and get QB4.
  849.        2) QCalc will work perfectly as a called sub rather than a
  850.           Function, however, you will _not_ get the calculator
  851.           result returned.  This means, the user will need to calculate
  852.           a list of entries or figures, write down or remember the result,
  853.           then manually re-enter it into the program - hardly ideal.
  854.  
  855.        Quick C
  856.        1) QCalc was briefly tested with the MS Quick C compiler, and found
  857.           to work ok.  There may be certain peculiarities with Quick C that
  858.           I am unaware of, but I am not a fan of QC and do not wish to
  859.           spend any more time with it than I need to.
  860.  
  861.  
  862.  
  863.  
  864.                 D.    FlexMenu
  865.  
  866.  
  867.     Flexmenu is a snappy, full featured, multi purpose menu-select
  868.     subprogram that supports a plethora of features with a minimum of setup
  869.     or parameters to manage.
  870.  
  871.     Many of the programs we write require easy to use and intuitive menus
  872.     for novices, yet navigation still needs to be flexible enough so as not
  873.     to frustrate experts.  We routinely use FlexMenu in these situations
  874.     because it fits all these needs and more.
  875.  
  876.     Syntax:
  877.     item = MenuChoice% (Menu$(), Trow%, LCol%, Nattr%, Hattr%, title$,_
  878.                  Mark%(), XtdChc%)
  879.  
  880.  
  881.     Using the list of items in menu$(), Flexmenu displays a box on the
  882.     screen at the location specified by TRow, LCol.  FlexMenu automagically
  883.     calculates the rest of the coordinates (length and width).  If the
  884.     number of choices is greater than 14, the box is truncated to hold the
  885.     first 14, with the rest being displayed thru the use of the arrow keys.
  886.     When this is the case, and selections are off the screen either above or
  887.     below, up and/or down arrows (ASCII 24 and 25) will be located on the
  888.     right border.
  889.  
  890.  
  891.     The list of choices or menu items is in the color attribute specified by
  892.     Nattr (Normal ATTRibute), and the current selection is highlighted in
  893.     color HAttr.  An optional title is centered across the top of the box.
  894.  
  895.     FlexMenu will elegantly handle as many choices as you can fit into
  896.     string space.  As we mentioned, for appearances, the box is never larger
  897.     than 14 selections.  Navigation is intuitively managed with the arrow
  898.     keys (Up and Down), Pg Up, Pg Dn, Home and End - all doing what you
  899.     would expect.  Additionally, FlexMenu responds to a alpha search -
  900.     press "A" will locate and go to (but not select) the first item after
  901.     our current item starting with "A" or "a".  Pressing [Enter] returns to
  902.     your code the index number of the item pressed.  If we are on item
  903.     1527, 'item' will be set to 1527.
  904.  
  905.  
  906.     We would find FlexMenu highly useful if that was all it did but it does
  907.     much, MUCH more:
  908.     First, it can automatically center the display (which we use almost
  909.     exclusively) by setting both TRow and LCol to -1.  This prevents you
  910.     from having to twiddle and map out where the center is.
  911.  
  912.     Next, it responds to extended keystrokes.  If we highlight item 156, and
  913.     press enter, item is set to 156.  If we press [Alt-Q] instead, item is
  914.     still set to 156, but the extended choice parameter (XtdChc) is set to
  915.     16 (the ASCII code for Alt-Q).  This allows us to manage multiple
  916.     functions from one menu.  For example, we might use DIR to load a string
  917.     array and FlexMenu to display the file names and from that, [Alt-D]
  918.     might delete the chosen file, but [Alt-L] might list it.  Then via a
  919.     SELECT CASE statement the desired functions can be swiftly carried out.
  920.  
  921.  
  922.  
  923.     To filter out unwanted extended choices, simply place the call to
  924.     FlexMenu in a DO or WHILE loop:
  925.  
  926.     done = 0
  927.     DO
  928.  
  929.        item = MenuChoice=(Menu$(), -1, -1, 78, 3, "Demo", Mark(), XtdChc)
  930.  
  931.        SELECT CASE XtdChc
  932.            CASE 1, 2, 3, 4
  933.                 GOSUB MoreChoices
  934.  
  935.            CASE 12, 14, 15
  936.                 GOSUB SomeStuff
  937.  
  938.            CASE 16
  939.                 GOSUB KillFile
  940.  
  941.            CASE 23
  942.              ' get another selection
  943.              CLS
  944.              item = MenuChoice(FList$(), -1, -1, 78, 3, "Demo", Mark(), XtdChc)
  945.              IF (XtdCHC <> 27) AND (Item > 0 ) THEN
  946.                  GOSUB GoodStuff
  947.              END IF
  948.              CLS        ' clear for next loop
  949.  
  950.  
  951.            CASE 27                              ' Escape
  952.                 done = 1
  953.                 SYSTEM
  954.  
  955.            CASE 18                              ' Alt - Q
  956.                done = 1
  957.  
  958.            CASE ELSE
  959.                'unsupported functions
  960.         END SELECT
  961.  
  962.     LOOP UNTIL done
  963.  
  964.  
  965.     In this type of construction, we limit the methods of ending the program
  966.     to the 2 we are prepared to handle.  In this way, the display (menu$() )
  967.     can represent either a lift of things to act upon such as file names or
  968.     a list of actions or a menu itself!  Creativity in nesting allows
  969.     virtually unlimited possibilities -- we have one program that manages
  970.     some 40,000 items and menu functions in 5 FlexMenu calls.  The novice
  971.     user is always interacting with FlexMenu, never DOS or the engine of the
  972.     program.
  973.  
  974.  
  975.  
  976.     There is even more!
  977.  
  978.     Flexmenu optionally supports a "Mark Mode" or multiple select function.
  979.     By setting XtdChc to non zero upon entry, you enable mark mode where
  980.     pressing the TAB, asterisk or SPACEBAR toggles a mark for that item.
  981.     The number of marks allowed is set by XtdChc, setting it to 10
  982.     allows 10 - and only 10 - items to be marked, set to 5, only 5 would be
  983.     allowed and so forth.  Marked items are tagged with bracketing "»" and
  984.     "«" (ASCII 174 and 175) characters (only on the display!  FlexMenu will
  985.     not alter your menu array!), and all the other features remain in
  986.     effect - alpha search, navigation and Extended keyboard selection.
  987.  
  988.     To accomplish this, you must pass an array that is of the same size as
  989.     your main selection string array.  FlexMenu will use this as a set of
  990.     pointers indicating which items are Marked: if elements 5, 6, 10 and 37
  991.     are set (non zero) upon exiting, then the user selected or marked
  992.     selections 5,6, 10 and 37 from the menu.  Item will STILL return as the
  993.     highlighted or current item when ENTER or an extended key is pressed -
  994.     it is up to you to use it or not.  If the Mark integer array is not the
  995.     same size as the string array of choices, item is set to -1 and FlexMenu
  996.     aborts.  However, if mark mode is NOT desired, enter FlexMenu with
  997.     XtdChc set to 0 and dimension Mark() to a single dimension.
  998.  
  999.  
  1000.     FlexMenu will also "remember" previous marks upon subsequent calls
  1001.     unless you REDIM the MARK array.  FlexMenu examines Mark() as it is
  1002.     setting up and treats non zero elements as marks.  That is, upon
  1003.     initializing it does not assume that it is the first time.  Using this,
  1004.     you can "suggest" selections by setting the corresponding Mark() element
  1005.     before calling FlexMenu - the user can of course toggle it off, but in
  1006.     cyclical applications, the user need not remark previous selections.
  1007.  
  1008.  
  1009.     We use FlexMenu almost exclusively in our menu driven applications,
  1010.     since it is powerful, fast, relatively small and has so many features
  1011.     and have found it to meet most every need.  If there is any interest, we
  1012.     could be persuaded into developing a version that uses a Fixed Length
  1013.     String Arrays or one that supports rodents.
  1014.  
  1015.  
  1016.     NOTE: FlexMenu requires the QPrint, Scroll, Painter and Boxes object
  1017.           modules.
  1018.  
  1019.     NOTE ALSO: FlexMenu is the name we have given the module or routine,
  1020.                but it is invoked as MenuChoice.  The term "MenuChoice"
  1021.                looks better in the code, but "FlexMenu" is much more
  1022.                descriptive of the routine when describing it in
  1023.                documentation.
  1024.  
  1025.  
  1026.  
  1027.                 E.  StatLine
  1028.  
  1029.     I. Overview
  1030.  
  1031.     StaLine is the name of the object file containing several routines or
  1032.     primitives that aid you in displaying and/or controlling a one or two
  1033.     row status line.
  1034.  
  1035.     These routines are:
  1036.  
  1037.     CLX - Clear the screen except for the status line area.
  1038.     SetBline - Set the bottom line of the non status line area of the
  1039.                screen.  Similar in function to the BASIC WINDOW statment.
  1040.     PrintStatL - Prints all or part of an array designated for the status
  1041.                  line.
  1042.  
  1043.  
  1044.     II.   Operation
  1045.  
  1046.     The default bottom line of a screen using StatLine procedures is row
  1047.     23, or a 2 row status line as used in the demo.  You can set this to
  1048.     more or less depending on your needs, thus allowing you to use even 5
  1049.     lines for the status area or even simulating a split screen effect.
  1050.  
  1051.     If you use more than 1 or 2 rows for the status line however, you will
  1052.     need to maintain those above 24 as PrintStatL will only print to lines
  1053.     24 and/or 25).  Beyond that limitation, these routines allow for
  1054.     printing and updating a status line, and clearing the non status line
  1055.     portion of the screen.
  1056.  
  1057.  
  1058.  
  1059.     III. Functions
  1060.  
  1061.     Name: SetBVLine            Type: SUB                     Level: ASM
  1062.     Syntax: CALL SetBVLine(x)
  1063.  
  1064.     As mentioned, the default bottom line of a screen using StatLine
  1065.     procedures is row 23, or a 2 row status line as used in the demo. If
  1066.     you with to reserve more or less area than that, SetBVLine will allow
  1067.     you to Set the Bottom Video Line to be respected by PrintStatL and CLX.
  1068.  
  1069.     Note that if you set it to 23, a call to CLX will ONLY clear lines 1 to
  1070.     23, saving the bottom two status lines and preventing you from having
  1071.     to redraw them.  However, CLS will still clear the entire screen.
  1072.  
  1073.  
  1074.  
  1075.     Name: CLX                 Type: SUB                     Level: ASM
  1076.     Syntax: CALL CLX
  1077.     This may also be called or invoked as ClrScrn
  1078.  
  1079.     This simply clears the non status line portion of the screen.  Where
  1080.     CLS would clear all 25 rows of video, CLX respects the default bottom
  1081.     video line of 22 or whatever you have set it to using SetBVLine.
  1082.  
  1083.     As with CLS, this will clear the screen, and locate both the PHYSICAL
  1084.     cursor position to 1,1 and reset the BASIC cursor location variables to
  1085.     1,1 also!  No need to LOCATE 1,1 after a CLX simply to let QB know that
  1086.     we cleared the screen.
  1087.  
  1088.  
  1089.  
  1090.     Name: PrintStatL          Type: SUB                     Level: ASM
  1091.     Syntax: CALL PrintStatL(StatMsg(1), Action, Attr)
  1092.     This may also be invoked as PrtSL
  1093.  
  1094.  
  1095.     This prints all or part of a 2 element fixed length 80 character string
  1096.     array to the status line area of the screen in the designted color.
  1097.  
  1098.     1. To pass a fixed length string array to a CALLed ASM sub, you
  1099.        must hide it in a TYPE structure by setting up a user defined TYPE
  1100.        that is simply a single 80 character string.
  1101.        Ex:
  1102.  
  1103.        TYPE struct                      ' tell QB what it looks like
  1104.           fls AS STRING * 80
  1105.        END TYPE
  1106.  
  1107.        DIM StatMsg(2) AS struct         ' order one
  1108.  
  1109.  
  1110.     2. Also to pass a TYPE structure to an ASM routine, you must DECLARE
  1111.        it using the keyword ANY.  So the DECALRE for PrtSL would be:
  1112.  
  1113.        DECALRE SUB PrtSL(MsgArry AS ANY, Action%, Attr%)
  1114.  
  1115.  
  1116.     3. At this point, we may fill the array with messages.  Feel free to
  1117.        use LSET or RSET with the array to justify strings.
  1118.        Ex:
  1119.        StatMsg(1).fls = "  Time: " + TIME$ + "   Temp: "+ degree$ + msg$
  1120.        StatMsg(2).fls = "  Code: " + Information$
  1121.  
  1122.     4. Finally invoke it with the desired action code and attribute:
  1123.        CALL PrtSL(StatMsg(1), 0, Attr)
  1124.  
  1125.  
  1126.  
  1127.     Action codes tell PrtSl what action to perform:
  1128.      0 = Print/Update both lines 24 and 25
  1129.      1 = Print/update line 24 only
  1130.      2 = Print/update line 25 only
  1131.  
  1132.  
  1133.     In more sophisticated applications, you can define more than 2 elements
  1134.     for the message array and selectively update higher offsets in the
  1135.     array.  For instance, if your program has 5 main function levels, you
  1136.     might need 5 different status line displays.  Using a 2 line display
  1137.     means we need 10 elements so,
  1138.  
  1139.        DIM StatMsg(10) AS struct         ' set up 5 status line SETS
  1140.  
  1141.     When we are working on the Main or top level we invoke elements
  1142.     1 and 2 to print to lines 24 and 25 as normal (above).  For subsequent
  1143.     levels we pass the element to be mapped or printed to line 24, the
  1144.     second activity level would be:
  1145.  
  1146.        CALL PrtSL(StatMsg(3), 0, Attr)
  1147.        ' element 3 goes to 24, 4 to line 25
  1148.  
  1149.     ' level 3:
  1150.        CALL PrtSL(StatMsg(5), 0, Attr)
  1151.  
  1152.     and so on to level 5:
  1153.        CALL PrtSL(StatMsg(9), 0, Attr)
  1154.  
  1155.     Of course, your use of OPTION BASE 0 means you subtract one from the
  1156.     element passed.
  1157.  
  1158.  
  1159.     Notes:
  1160.     Being a fixed length string, a very large number of status line
  1161.     messages can be stored in your fixed length sting array, but be sure
  1162.     to use the /ah switch if the arry is to be more than 64k
  1163.  
  1164.     QB inititializes a fixed length string to NULLs, NOT SPACES, so
  1165.     displaying a messgae arry that you have not added text to, may result
  1166.     in unexpected results.
  1167.  
  1168.  
  1169.  
  1170.     PrntSL expects a 2 line status area, so to use only line 25, your
  1171.     message array would still have to be 2 elements per "level", but every
  1172.     other one would be blank or NULL.  MsgArry(1) always maps to line 24,
  1173.     as does 3, 5, 7, 9 etc.  These would be blank, but 2, 4, 6, 8 etc
  1174.     would be filled for mapping to line 25 when you want to use only line
  1175.     25.
  1176.  
  1177.     SetBVLine has no effect on PrtSL only on CLX.
  1178.  
  1179.     PrtSL expects the message arry to print to be a 80 character sting
  1180.     array - if you dimension it to a smaller number the memory contents
  1181.     immediately following the arry will be printed.  Ex: if you DIM it to
  1182.     STRING * 60 (rather than 80), line 24 would display the first element
  1183.     PLUS the first 20 characters of the second, and the bottom line would
  1184.     display the next 40 characters of the second element PLUS what ever
  1185.     garbage is in the next 40 bytes of memory.
  1186.  
  1187.  
  1188.  
  1189.